package com.kun.companion.core.util;

import com.kun.companion.core.AbstractApplication;
import com.kun.companion.core.exception.Assert;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 高性能图片加载工具类（采用双检锁缓存机制）
 *
 * @author gzc
 */
public class ImageLoader {
    private static final Logger log = LoggerFactory.getLogger(ImageLoader.class);
    private static final float DEFAULT_LOAD_RATIO = 0.75f;
    private static final int MAX_CACHE_SIZE = 10;

    /**
     * LRU策略的线程安全缓存
     */
    private static volatile Map<String, Image> imageCache;

    static {
        initializeCache();
    }

    private static synchronized void initializeCache() {
        if (imageCache == null) {
            imageCache = Collections.synchronizedMap(
                    new LimitedCache<>(MAX_CACHE_SIZE, DEFAULT_LOAD_RATIO, true)
            );
        }
    }

    /**
     * 加载图片（带默认尺寸）
     *
     * @param resourcePath 资源路径（相对于resources目录）
     * @return 加载成功的Image对象或null
     */
    public static Image load(String resourcePath) {
        return load(resourcePath, -1, -1, true);
    }

    /**
     * 按需缩放加载图片
     *
     * @param resourcePath 资源路径
     * @param width        目标宽度（<=0时保持原始尺寸）
     * @param height       目标高度（<=0时保持原始尺寸）
     * @return 加载成功的Image对象或null
     */
    public static Image load(String resourcePath, double width, double height) {
        return load(resourcePath, width, height, true);
    }

    /**
     * 核心加载方法
     *
     * @param preserveRatio 是否保持宽高比
     */
    private static Image load(String resourcePath, double width, double height, boolean preserveRatio) {
        try {
            String cacheKey = buildCacheKey(resourcePath, width, height);

            // 双检锁缓存查询
            Image cached = imageCache.get(cacheKey);
            if (cached != null && !cached.isError()) {
                return cached;
            }

            // 资源存在性预检
            URL resource = AbstractApplication.getLoader().getResource(resourcePath);
            Assert.notNull(resource, "图片资源【{}】未找到", resourcePath);

            // 异步加载（后台线程加载，不阻塞UI）
            Image newImage = new Image(
                    Objects.requireNonNull(ImageLoader.class.getResourceAsStream(resourcePath)),
                    width > 0 ? width : -1,
                    height > 0 ? height : -1,
                    preserveRatio,
                    true
            );

            // 添加加载完成监听
            newImage.progressProperty().addListener((obs, oldVal, newVal) -> {
                if (newVal.doubleValue() >= 1.0) {
                    synchronized (ImageLoader.class) {
                        imageCache.put(cacheKey, newImage);
                    }
                }
            });

            return newImage;
        } catch (Exception e) {
            Assert.throwBizException(e, "图片加载失败，图片路径【{}】，失败原因: {}", resourcePath, e.getMessage());
        }
        return null;
    }

    public static ImageView loadView(String resourcePath, double width, double height) {
        Image image = load(resourcePath);
        ImageView imageView = new ImageView();
        imageView.setFitWidth(width);
        imageView.setFitHeight(height);
        imageView.setSmooth(true);
        imageView.setImage(image);
        return imageView;
    }

    public static ImageView loadView(String resourcePath, double width, double height, boolean preserveRatio) {
        Image image = load(resourcePath);
        ImageView imageView = new ImageView();
        imageView.setFitWidth(width);
        imageView.setFitHeight(height);
        imageView.setSmooth(preserveRatio);
        imageView.setImage(image);
        return imageView;
    }



    /**
     * 生成唯一缓存键（尺寸敏感）
     */
    private static String buildCacheKey(String path, double width, double height) {
        return String.format("%s@%.0fx%.0f", path, width, height);
    }

    /**
     * 自定义LRU缓存实现
     */
    private static class LimitedCache<K, V> extends LinkedHashMap<K, V> {
        private final int maxCapacity;

        LimitedCache(int initialCapacity, float loadFactor, boolean accessOrder) {
            super(initialCapacity, loadFactor, accessOrder);
            this.maxCapacity = initialCapacity;
        }

        @Override
        protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
            // 当缓存大小超过容量时，移除最旧的条目
            return size() > maxCapacity;
        }
    }

}